
/**
 * We Are A Team
 * 
 * 题目描述

总共有 n 个人在机房，每个人有一个标号（1<=标号<=n），他们分成了多个团队，需要你根据收到的 m 条消息判定指定的两个人是否在一个团队中，具体的：

消息构成为 a b c，整数 a、b 分别代表两个人的标号，整数 c 代表指令
c == 0 代表 a 和 b 在一个团队内
c == 1 代表需要判定 a 和 b 的关系，如果 a 和 b 是一个团队，输出一行’we are a team’,如果不是，输出一行’we are not a team’
c 为其他值，或当前行 a 或 b 超出 1~n 的范围，输出‘da pian zi’


输入描述
第一行包含两个整数 n，m(1<=n,m<100000),分别表示有 n 个人和 m 条消息
随后的 m 行，每行一条消息，消息格式为：a b c(1<=a,b<=n,0<=c<=1)
输出描述
c ==1,根据 a 和 b 是否在一个团队中输出一行字符串，在一个团队中输出‘we are a team‘,不在一个团队中输出’we are not a team’
c 为其他值，或当前行 a 或 b 的标号小于 1 或者大于 n 时，输出字符串‘da pian zi‘
如果第一行 n 和 m 的值超出约定的范围时，输出字符串”NULL“。
用例
输入	5 7
1 2 0
4 5 0
2 3 0
1 2 1
2 3 1
4 5 1
1 5 1
输出	we are a team
we are a team
we are a team
we are not a team
说明	无
输入	5 6
1 2 0
1 2 1
1 5 0
2 3 1
2 5 1
1 3 2
输出	we are a team
we are not a team
we are a team
da pian zi
说明	无

 */

import java.util.Arrays;
import java.util.Scanner;

/**
 * 
 * 题目解析
 * 本题可以使用 并查集 建立 a,b 的关联关系。
 * 
 * 2023.09.19
 * 
 * 本题c == 1判断a,b是否处于一个团队时，本题判断范围存在歧义，当前有两种思路：
 * 
 * 1、仅限判断前面行中建立的关系中，a,b是否处于同一团队
 * 
 * 2、不限于前面行，而是等所有行输入完后，才判断a,b是否处于同一团队
 * 
 * 下面对这两种思路都进行实现下，代码上差别不大，考试时可以都试下
 * 
 */
public class WeAreATeam {

    public static void main(String[] args) {

        try {

            Scanner scanner = new Scanner(System.in);

            // 人数
            int n = scanner.nextInt();
            // 指令数
            int m = scanner.nextInt();
            // 指令集合
            int[][] commandArr = new int[m][3];
            for (int i = 0; i < m; i++) {
                commandArr[i][0] = scanner.nextInt();
                commandArr[i][1] = scanner.nextInt();
                commandArr[i][2] = scanner.nextInt();
            }

            // 如果第一行 n 和 m 的值超出约定的范围时，输出字符串”Null“。
            // 1<=n,m<100000
            if (n < 1 || n >= 100000 || m < 1 || m >= 100000) {
                System.out.println("NULL");
                return;
            }

            // 构建并查集
            UnionSet unionSet = new UnionSet(n + 1);

            // 如果第一行 n 和 m 的值超出约定的范围时，输出字符串”Null“。

            // 构建关联关系
            Arrays.stream(commandArr).filter(c -> c[2] == 0 && c[0] >= 1 && c[0] <= n && c[1] >= 1 && c[1] <= n)
                    .forEach(c -> unionSet.union(c[0], c[1]));

            for (int[] msg : commandArr) {
                int a = msg[0], b = msg[1], c = msg[2];

                if (a < 1 || a > n || b < 1 || b > n) {
                    // 当前行 a 或 b 的标号小于 1 或者大于 n 时，输出字符串‘da pian zi‘
                    System.out.println("da pian zi");
                    continue;
                }

                if (c == 0) {
                } else if (c == 1) {
                    // c == 1 代表需要判定 a 和 b 的关系，如果 a 和 b 是一个团队，输出一行’we are a team’,如果不是，输出一行’we are
                    // not a team’
                    System.out.println(unionSet.find(a) == unionSet.find(b) ? "we are a team" : "we are not a team");
                } else {
                    // c 为其他值，输出字符串‘da pian zi‘
                    System.out.println("da pian zi");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 并查集主要用于解决一些元素分组的问题。它管理一系列不相交的集合，并支持两种操作：
     * 
     * 合并（Union）：把两个不相交的集合合并为一个集合。
     * 查询（Find）：查询两个元素是否在同一个集合中。
     * 当然，这样的定义未免太过学术化，看完后恐怕不太能理解它具体有什么用。所以我们先来看看并查集最直接的一个应用场景：亲戚问题。
     * 并查集的重要思想在于，用集合中的一个元素代表集合。我曾看过一个有趣的比喻，把集合比喻成帮派，而代表元素则是帮主。接下来我们利用这个比喻，看看并查集是如何运作的。
     * 
     * 
     */
    private static class UnionSet {

        int[] arr;

        public UnionSet(int n) {
            arr = new int[n];
            for (int i = 0; i < n; i++) {

                arr[i] = i;

            }

        }

        public int find(int x) {

            if (x == arr[x])
                return x;
            return arr[x] = find(arr[x]);
        }

        public void union(int x, int y) {

            int xV = find(x);
            int yV = find(y);

            if (xV != yV) {

                arr[yV] = xV;
            }
        }

    }
}
